using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/****************************************************
// 功能：基础表现单位
// | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
// | Copyright (c) 2021-2025 聊来 All rights reserved.
// | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">聊来</a> )
// | @Author: 贯彻己道的云 <18970881148@qq.com>
// | DateTime: 2025/3/31 17:30:54
*****************************************************/

public abstract class ViewUnit : MonoBehaviour
{
    public bool isSyncPos;

    public bool isSyncDir;

    public Transform rotationRoot;

    public LogicUnit logicUnit = null;

    // 是否开启预测位置
    public bool preditPosition;
    // 最大预测数量
    public int predictMaxCount;
    // 是否开启平滑
    public bool smoothPosition;
    public bool smoothDir;
    // 平滑加速度
    public float viewPositionAccer;
    // 方向角度加速度
    public float viewDirAccer;
    public float AngleMultiplier;

    // 预测数量
    private int preditCount;
    // 表现层目标位置
    protected Vector3 viewTargetPosition;
    // 表现层目标方向
    protected Vector3 viewTargetDir;

    public virtual void Init(LogicUnit logicUnit)
    {
        this.logicUnit = logicUnit;
        var game = gameObject;
        game.name = $"{logicUnit.unitName}_{game.name}";

        transform.position = logicUnit.LogicPos.ConvertViewVector3();
        if (rotationRoot == null)
        {
            rotationRoot = transform;
        }

        rotationRoot.rotation = CalcRotation(logicUnit.LogicDir.ConvertViewVector3());
    }

    private void UpdateDirection()
    {
        if (logicUnit.isDirChanged)
        {
            viewTargetDir = GetUnitViewDir();
            logicUnit.isDirChanged = false;
        }

        if (smoothDir)
        {
            var threshold = Time.deltaTime * viewDirAccer;
            var angle = Vector3.Angle(rotationRoot.forward, viewTargetDir);
            var angleMult = (angle / 180) * AngleMultiplier * Time.deltaTime;

            if (viewTargetDir != Vector3.zero)
            {
                var interDir = Vector3.Lerp(rotationRoot.forward, viewTargetDir, threshold + angleMult);
                rotationRoot.rotation = CalcRotation(interDir);
            }
        }
        else
        {
            rotationRoot.rotation = CalcRotation(viewTargetDir);
        }
    }

    private void UpdatePosition()
    {
        if (preditPosition)
        {
            if (logicUnit.isPosChanged)
            {
                // 逻辑有Tick，目标位置更新到最新
                viewTargetPosition = logicUnit.LogicPos.ConvertViewVector3();
                logicUnit.isPosChanged = false;
                preditCount = 0;
            }
            else
            {
                // 逻辑未Tick，使用预测计算
                if (preditCount > predictMaxCount) { return; }
                var delta = Time.deltaTime;
                // 预测位置 = 上一帧到当前帧的秒间隔 * 逻辑速度 * 逻辑方向
                var predictPos = delta * logicUnit.LogicMoveSpeed.RawFloat * logicUnit.LogicDir.ConvertViewVector3();
                // 新的目标位置 = 表现目标位置 + 预测位置
                viewTargetPosition += predictPos;
                ++preditCount;
            }

            // 平滑移动
            if (smoothPosition)
            {
                transform.position = Vector3.Lerp(transform.position, viewTargetPosition,
                    Time.deltaTime * viewPositionAccer);
            }
            else
            {
                transform.position = viewTargetPosition; 
            }

            
        }
        else
        {
            ForcePositionSync();
        }
        
    }

    /// <summary>
    /// 强制位置同步
    /// </summary>
    private void ForcePositionSync()
    {
        transform.position = logicUnit.LogicPos.ConvertViewVector3();
    }

    /// <summary>
    /// 基于当前朝向计算旋转的量
    /// </summary>
    /// <param name="targetDir"></param>
    /// <returns></returns>
    protected Quaternion CalcRotation(Vector3 targetDir)
    {
        return Quaternion.FromToRotation(Vector3.forward, targetDir);
    }
    
    protected virtual Vector3 GetUnitViewDir()
    {
        return logicUnit.LogicDir.ConvertViewVector3();
    }

    public void ForcePosSync() {
        transform.position = logicUnit.LogicPos.ConvertViewVector3();
    }
    
    public virtual void PlayAni(string aniName) { }

    public virtual void PlayAudio(string audioName, bool loop = false, int delay = 0)
    {
        AudioManager.Instance.PlayEntityAudio(audioName, GetComponent<AudioSource>(), loop, delay);
    }

    
    protected virtual void Update()
    {
        if (isSyncDir)
        {
            UpdateDirection();
        }

        if (isSyncPos)
        {
            UpdatePosition();
        }
    }
}
